package com.hs.hlw.credit.system.business.service.impl;

import com.hs.hlw.credit.system.business.dto.ResponseDto;
import com.hs.hlw.credit.system.business.service.SubmissionFormService;
import com.hs.hlw.credit.system.common.enumeration.*;
import com.hs.hlw.credit.system.data.mybatis.Pageable;
import com.hs.hlw.credit.system.data.primary.mapper.DataSourceMapper;
import com.hs.hlw.credit.system.data.primary.mapper.SubmissionFormFieldMapper;
import com.hs.hlw.credit.system.data.primary.mapper.SubmissionFormMapper;
import com.hs.hlw.credit.system.data.primary.model.DataSource;
import com.hs.hlw.credit.system.data.primary.model.SubmissionForm;
import com.hs.hlw.credit.system.data.primary.model.SubmissionFormField;
import com.hs.hlw.credit.system.data.primary.model.SubmissionFormFieldExample;
import com.hs.hlw.credit.system.data.secondary.mapper.TableFileMapper;
import com.hs.hlw.credit.system.data.secondary.model.TableFile;
import com.hualongdata.exception.BusinessException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * SubmissionFormServiceImpl
 * @author zhb
 * @date 2018/11/19
 */
@Service
public class SubmissionFormServiceImpl implements SubmissionFormService {
    private static final int FIELD_PLACEHOLDER_LENGTH_MAX = 100;
    private @Autowired SubmissionFormMapper submissionFormMapper;
    private @Autowired SubmissionFormFieldMapper submissionFormFieldMapper;
    private @Autowired DataSourceMapper dataSourceMapper;
    private @Autowired TableFileMapper tableFileMapper;

    /**
     * 新增
     * @param submissionForm
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public ResponseDto add(SubmissionForm submissionForm) {
        DataSource dataSource = dataSourceMapper.selectByPrimaryKey(submissionForm.getDataSourceId());
        if (dataSource == null) {
            throw new BusinessException("数据源不存在");
        }
        TableFile tableFile = tableFileMapper.selectByPrimaryKey(submissionForm.getTableId());
        if (tableFile == null || !dataSource.getEnglishName().equals(tableFile.getDbname())) {
            throw new BusinessException("数据库表不存在");
        }
        submissionForm.setDbName(dataSource.getEnglishName());
        submissionForm.setTableName(tableFile.getDataname());

        // 校验字段列表
        checkFieldList(submissionForm.getFieldList());

        // 保存表单信息
        submissionForm.setCreateTime(new Date());
        submissionFormMapper.insertSelective(submissionForm);

        // 保存字段信息
        for (SubmissionFormField field : submissionForm.getFieldList()) {
            field.setFormId(submissionForm.getId());
            submissionFormFieldMapper.insertSelective(field);
        }

        Map<String, Object> data = new HashMap<>();
        data.put("id", submissionForm.getId());
        return new ResponseDto("新增成功", data);
    }

    /**
     * 更新
     * @param submissionForm
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public ResponseDto update(SubmissionForm submissionForm) {
        DataSource dataSource = dataSourceMapper.selectByPrimaryKey(submissionForm.getDataSourceId());
        if (dataSource == null) {
            throw new BusinessException("数据源不存在");
        }
        TableFile tableFile = tableFileMapper.selectByPrimaryKey(submissionForm.getTableId());
        if (tableFile == null || !dataSource.getEnglishName().equals(tableFile.getDbname())) {
            throw new BusinessException("数据库表不存在");
        }
        submissionForm.setDbName(dataSource.getEnglishName());
        submissionForm.setTableName(tableFile.getDataname());

        // 校验字段列表
        checkFieldList(submissionForm.getFieldList());

        // 保存表单信息
        submissionForm.setUpdateTime(new Date());
        submissionFormMapper.updateByPrimaryKeySelective(submissionForm);

        // 获除数据库中无用字段
        SubmissionFormFieldExample example = new SubmissionFormFieldExample();
        SubmissionFormFieldExample.Criteria criteria = example.createCriteria();
        criteria.andFormIdEqualTo(submissionForm.getId());
        List<SubmissionFormField> list = submissionFormFieldMapper.selectByExample(example);
        Map<String, SubmissionFormField> codeMap = new HashMap<>();
        for (SubmissionFormField field : submissionForm.getFieldList()) {
            codeMap.put(field.getFieldCode(), field);
        }
        if (list != null && !list.isEmpty()) {
            for (SubmissionFormField field : list) {
                if (!codeMap.containsKey(field.getFieldCode())) {
                    submissionFormFieldMapper.deleteByPrimaryKey(field.getId());
                } else {
                    codeMap.get(field.getFieldCode()).setId(field.getId());
                }
            }
        }

        // 保存字段信息
        for (SubmissionFormField field : submissionForm.getFieldList()) {
            field.setFormId(submissionForm.getId());
            if (field.getId() == null) {
                submissionFormFieldMapper.insertSelective(field);
            } else {
                SubmissionFormField dto = submissionFormFieldMapper.selectByPrimaryKey(field.getId());
                // 如果输入类型与之前的一样，则更不更新规则配置，否则把规则配置清空
                if (field.getInputType().equals(dto.getInputType())) {
                    submissionFormFieldMapper.updateByPrimaryKeySelective(field);
                } else {
                    submissionFormFieldMapper.updateByPrimaryKey(field);
                }
            }
        }

        return new ResponseDto("更新成功");
    }

    /**
     * 分页查询
     * @param pageable
     * @return
     */
    public ResponseDto page(Pageable pageable) {
        List<SubmissionForm> list =  submissionFormMapper.page(pageable);
        return new ResponseDto("查询成功", pageable, list);
    }

    /**
     * 详情
     * @param id
     * @return
     */
    public ResponseDto detail(Integer id) {
        SubmissionForm submissionForm = submissionFormMapper.selectByPrimaryKey(id);
        if (submissionForm == null) {
            throw new BusinessException("表单不存在");
        }

        // 获取字段列表
        SubmissionFormFieldExample example = new SubmissionFormFieldExample();
        SubmissionFormFieldExample.Criteria criteria = example.createCriteria();
        criteria.andFormIdEqualTo(id);
        example.setOrderByClause("sort asc");
        List<SubmissionFormField> fieldList = submissionFormFieldMapper.selectByExample(example);
        submissionForm.setFieldList(fieldList);

        return new ResponseDto("查询成功", submissionForm);
    }

    /**
     * 批量更新状态
     * @param list
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public ResponseDto batchUpdateStatus(List<SubmissionForm> list) {
        Date time = new Date();
        for (SubmissionForm submissionForm : list) {
            submissionForm.setUpdateTime(time);
            submissionFormMapper.updateByPrimaryKeySelective(submissionForm);
        }

        return new ResponseDto("更新成功");
    }

    /**
     * 校验字段列表
     * @param fieldList
     */
    private void checkFieldList(List<SubmissionFormField> fieldList) {
        if (fieldList == null || fieldList.isEmpty()) {
            throw new BusinessException("表单字段不能为空");
        }
        Map<String, SubmissionFormField> codeMap = new HashMap<>();
        for (int i = 0; i < fieldList.size(); i++) {
            SubmissionFormField field = fieldList.get(i);
            if (StringUtils.isBlank(field.getFieldCode())) {
                throw new BusinessException("第" + (i + 1) + "个字段的英文名未填写");
            }
            if (codeMap.containsKey(field.getFieldCode())) {
                throw new BusinessException("第" + (i + 1) + "个字段的英文名重复");
            } else {
                codeMap.put(field.getFieldCode(), field);
            }
            if (StringUtils.isBlank(field.getFieldName())) {
                throw new BusinessException("第" + (i + 1) + "个字段的中文名未填写");
            }
            if (StringUtils.isBlank(field.getFieldDataType())) {
                throw new BusinessException("第" + (i + 1) + "个字段的类型未填写");
            }
            if (field.getInputType() == null) {
                throw new BusinessException("第" + (i + 1) + "个字段的表单类型未选择");
            }
            if (!FormFieldInputType.contains(field.getInputType())) {
                throw new BusinessException("第" + (i + 1) + "个字段的表单类型选择有误");
            }
            if (field.getRequired() == null) {
                throw new BusinessException("第" + (i + 1) + "个字段的是否必填未指定");
            }
            if (!FormFieldRequiredStatus.contains(field.getRequired())) {
                throw new BusinessException("第" + (i + 1) + "个字段的是否必填指定有误");
            }
            if (field.getIsReadOnly() == null) {
                throw new BusinessException("第" + (i + 1) + "个字段的是否只读未指定");
            }
            if (!FormFieldReadOnlyStatus.contains(field.getIsReadOnly())) {
                throw new BusinessException("第" + (i + 1) + "个字段的是否只读指定有误");
            }
            if (field.getDisplayStatus() == null) {
                throw new BusinessException("第" + (i + 1) + "个字段的显示状态未指定");
            }
            if (!FormFieldDisplayStatus.contains(field.getDisplayStatus())) {
                throw new BusinessException("第" + (i + 1) + "个字段的显示状态指定有误");
            }
            if (StringUtils.isNotBlank(field.getPlaceholder()) && field.getPlaceholder().length() > FIELD_PLACEHOLDER_LENGTH_MAX) {
                throw new BusinessException("第" + (i + 1) + "个字段的输入提示不能超过" + FIELD_PLACEHOLDER_LENGTH_MAX + "个字符");
            }
            if (field.getSort() == null) {
                throw new BusinessException("第" + (i + 1) + "个字段的排序未指定");
            }
            if (field.getIsSearchCondition() == null) {
                throw new BusinessException("第" + (i + 1) + "个字段未选择是否可用作查询条件");
            }
            if (!CommonStatus.contains(field.getIsSearchCondition())) {
                throw new BusinessException("第" + (i + 1) + "个字段是否可用作查询条件指定有误");
            }
            if (field.getListDisplayStatus() == null) {
                throw new BusinessException("第" + (i + 1) + "个字段未选择是否是否可用作查询列表显示");
            }
            if (!CommonStatus.contains(field.getListDisplayStatus())) {
                throw new BusinessException("第" + (i + 1) + "个字段否是否可用作查询列表显示指定有误");
            }
        }
    }
}